package com.hyts.keygen.handler;

import com.hyts.keygen.config.KeyGenProperties;


/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.keygen.handler
 * @author:Libo/Alex
 * @create-date:2019-05-26 11:36
 * @copyright:libo-hyts-github
 * @email:libo2dev@aliyun.com
 * @description:此类主要用于: key 关键字ID构建数值生成器
 */
public class KeyIdGenerator {

    /**
     * 当前序列值
     */
    private long sequence = 0;

    /**
     * 最后一次请求时间戳
     */
    private long lastTimestamp = -1L;

    /**
     * 序列的位板
     */
    private long sequenceMask = -1L ^ (-1L << KeyGenProperties.SEQUENCE_BIT_COUNT);

    /**
     * 最后一次请求用户标识
     */
    private long lastTag=1L;


    public KeyIdGenerator(long sequence){
        this.sequence = sequence < 0 ? 0: sequence;
    }

    public KeyIdGenerator(){
        this.sequence = 0;
    }


    public Long nextId(long tag) {
        long timestamp = KeyTimeHandler.generate();
        if(tag<0){
            tag=-tag;
        }

        if (timestamp < lastTimestamp) {
            //LOG.error(String.format("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp));
            throw new RuntimeException(String.format(
                    "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = KeyTimeHandler.generateNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }

        if(tag==lastTag){
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = KeyTimeHandler.generateNextMillis(lastTimestamp);
            }
        }
        lastTag=tag;

        lastTimestamp = timestamp;

        return (timestamp << (KeyGenProperties.TOTAL_BIT_COUNT - KeyGenProperties.TIMESTAMP_BIT_COUNT))
                | ((tag % KeyGenProperties.REGION_MODEL_VAL) << (KeyGenProperties.TOTAL_BIT_COUNT -
                KeyGenProperties.TIMESTAMP_BIT_COUNT - KeyGenProperties.REGION_BIT_COUNT)) | sequence;
    }
}
